package org.net5ijy.cloud.plugin.feign.core.util;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Stack;

/**
 * DynamicClasspath
 *
 * @author XGF
 * @date 2020/11/17 9:22
 */
public class DynamicClasspath {

  public static void loadJar(String jar)
      throws NoSuchMethodException, MalformedURLException, InvocationTargetException, IllegalAccessException {

    File file = new File(jar);

    Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    method.setAccessible(true);

    URL url1 = new URL("file:" + file.getAbsolutePath());
    // 设置类加载器
    URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    // 将当前类路径加入到类加载器中
    method.invoke(classLoader, url1);
  }

  public static void loadLib(String libDir)
      throws NoSuchMethodException, MalformedURLException, InvocationTargetException, IllegalAccessException {

    File lib = new File(libDir);

    File[] files = lib.listFiles();

    Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    method.setAccessible(true);

    if (files == null) {
      throw new RuntimeException("未找到lib目录[" + lib.getName() + "]");
    }

    for (File file : files) {
      if (file.getName().endsWith("jar")) {
        URL url1 = new URL("file:" + file.getAbsolutePath());
        // 设置类加载器
        URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        // 将当前类路径加入到类加载器中
        method.invoke(classLoader, url1);
      }
    }
  }

  public static void loadDir(String dir)
      throws NoSuchMethodException, MalformedURLException, InvocationTargetException, IllegalAccessException {

    File programRootDir = new File(dir);

    URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

    Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    method.setAccessible(true);

    method.invoke(classLoader, programRootDir.toURI().toURL());
  }

  @Deprecated
  public static void loadClasses(String rootClassPath) throws Exception {

    // 设置class文件所在根路径
    File clazzPath = new File(rootClassPath);

    // 记录加载.class文件的数量
    int clazzCount = 0;

    if (clazzPath.exists() && clazzPath.isDirectory()) {
      // 获取路径长度
      int clazzPathLen = clazzPath.getAbsolutePath().length() + 1;

      Stack<File> stack = new Stack<>();
      stack.push(clazzPath);

      // 遍历类路径
      while (!stack.isEmpty()) {
        File path = stack.pop();
        File[] classFiles = path.listFiles(pathname -> {
          //只加载class文件
          return pathname.isDirectory() || pathname.getName().endsWith(".class");
        });
        if (classFiles == null) {
          break;
        }
        for (File subFile : classFiles) {
          if (subFile.isDirectory()) {
            stack.push(subFile);
          } else {
            if (clazzCount++ == 0) {
              Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
              boolean accessible = method.isAccessible();
              try {
                if (!accessible) {
                  method.setAccessible(true);
                }
                // 设置类加载器
                URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
                // 将当前类路径加入到类加载器中
                method.invoke(classLoader, clazzPath.toURI().toURL());
              } catch (Exception e) {
                e.printStackTrace();
              } finally {
                method.setAccessible(accessible);
              }
            }
            // 文件名称
            String className = subFile.getAbsolutePath();
            className = className.substring(clazzPathLen, className.length() - 6);
            //将/替换成. 得到全路径类名
            className = className.replace(File.separatorChar, '.');
            // 加载Class类
            Class.forName(className);
          }
        }
      }
    }
  }
}
